/*
 *    Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the pig4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: lengleng (wangiegie@gmail.com)
 */
package com.pig4cloud.pigx.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pig4cloud.pigx.common.core.util.R;
import com.pig4cloud.pigx.common.customize.enums.AbnormalEnum;
import com.pig4cloud.pigx.common.customize.exception.DuckweedException;
import com.pig4cloud.pigx.common.customize.mysql.utils.MysqlUtil;
import com.pig4cloud.pigx.common.customize.security.utils.SecurityUtil;
import com.pig4cloud.pigx.common.customize.utils.id.IdWorker;
import com.pig4cloud.pigx.common.security.service.PigxUser;
import com.pig4cloud.pigx.user.constant.WalletConstant;
import com.pig4cloud.pigx.user.dto.UpdateFuelBalanceDTO;
import com.pig4cloud.pigx.user.entity.FuelAccount;
import com.pig4cloud.pigx.user.entity.User;
import com.pig4cloud.pigx.user.mapper.FuelAccountMapper;
import com.pig4cloud.pigx.user.service.CurrencyService;
import com.pig4cloud.pigx.user.service.FuelAccountService;
import com.pig4cloud.pigx.user.vo.LoginUserFuelVO;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * 燃料账户
 *
 * @author pigx code generator
 * @date 2022-11-23 14:43:55
 */
@Service
@AllArgsConstructor
public class FuelAccountServiceImpl extends ServiceImpl<FuelAccountMapper, FuelAccount> implements FuelAccountService {

	private final IdWorker idWorker;

	private final CurrencyService currencyService;

	private final MysqlUtil mysqlUtil;

	/**
	 * 为用户生成燃料账户
	 * @param user 用户
	 */
	@Override
	public void createFuel(User user) {
		try {
			Long count = baseMapper.selectCount(new QueryWrapper<FuelAccount>() {{
				eq("user_id", user.getId());
			}});
			if (count > 0) {
				return;
			}
			// 默认只生成UNT账户
			FuelAccount account = new FuelAccount();
			account.setId(idWorker.nextId());
			account.setUserId(user.getId());
			account.setFrozen(BigDecimal.ZERO);
			// 演示版直接分配10000燃料费
			account.setBalance(BigDecimal.valueOf(10000));
			account.setCurrency(WalletConstant.USDT);
			baseMapper.insert(account);
		} catch (Exception e) {
			throw new DuckweedException(AbnormalEnum.MSG.DISCONNECTED);
		}
	}

	@Override
	public R<LoginUserFuelVO> getUserFuel() {
		PigxUser user = SecurityUtil.getLoginUser();
		if (user == null) {
			throw new DuckweedException(AbnormalEnum.MSG.OPTIONS_USER_NOT_FOUND);
		}
		try {
			FuelAccount fuelAccount = baseMapper.selectOne(new QueryWrapper<FuelAccount>() {{
				eq("user_id", user.getId());
			}});
			if (fuelAccount == null) {
				throw new DuckweedException(AbnormalEnum.MSG.OPTIONS_USER_NOT_FOUND.getCode(),"该用户未开通燃料账户");
			}
			LoginUserFuelVO vo = new LoginUserFuelVO();
			BeanUtils.copyProperties(fuelAccount,vo);
			vo.setBalance(vo.getBalance().setScale(2, RoundingMode.DOWN));
			return R.ok(vo);
		} catch (Exception e) {
			throw new DuckweedException(AbnormalEnum.MSG.DISCONNECTED);
		}
	}

	@Override
	public BigDecimal getBalance(Long userId,String currency) {
		FuelAccount fuelAccount = baseMapper.selectOne(new QueryWrapper<FuelAccount>() {{
			eq("user_id", userId);
			eq("currency", currency);
			select("balance");
		}});
		if (fuelAccount == null) {
			throw new DuckweedException(AbnormalEnum.MSG.OPTIONS_USER_NOT_FOUND.getCode(),"该用户未开通燃料账户");
		}
		return fuelAccount.getBalance();
	}

	@Override
	public BigDecimal updateBalance(UpdateFuelBalanceDTO dto) {
		try {
			mysqlUtil.startLocalTx();
			FuelAccount fuelAccount = baseMapper.selectOne(new QueryWrapper<FuelAccount>() {{
				eq("user_id", dto.getUserId());
				eq("currency", dto.getCurrency());
				last("for update");
			}});
			if (fuelAccount == null) {
				throw new DuckweedException(AbnormalEnum.MSG.OPTIONS_USER_NOT_FOUND.getCode(),"该用户未开通燃料账户");
			}
			BigDecimal change;
			if (dto.getIsAdd()) {
				change = fuelAccount.getBalance().add(dto.getQuantity());
			} else {
				change = fuelAccount.getBalance().subtract(dto.getQuantity());
			}
			fuelAccount.setBalance(change);
			baseMapper.updateById(fuelAccount);
			mysqlUtil.commitLocalTx();
			return change;
		} catch (DuckweedException e) {
			mysqlUtil.rollbackLocalTx();
			throw e;
		} catch (Exception e) {
			mysqlUtil.rollbackLocalTx();
			throw new DuckweedException(AbnormalEnum.MSG.DISCONNECTED.getCode(),"修改燃料账户失败");
		}
	}

}
